package io.gitee.zhangbinhub.admin.oauth.init

import com.mybatisflex.core.dialect.DbTypeUtil
import io.gitee.zhangbinhub.acp.boot.init.AcpInitialization
import io.gitee.zhangbinhub.acp.boot.log.LogAdapter
import io.gitee.zhangbinhub.admin.common.constant.DbConstant
import io.gitee.zhangbinhub.admin.common.constant.RoleCode
import io.gitee.zhangbinhub.admin.oauth.conf.AcpOauthServerAutoConfiguration
import io.gitee.zhangbinhub.admin.oauth.service.*
import org.noear.solon.Solon
import org.noear.solon.annotation.Component
import org.noear.solon.annotation.Inject
import org.noear.solon.core.util.ResourceUtil
import org.noear.solon.data.sql.SqlUtils
import javax.sql.DataSource

@Component
open class DataInitialization(
    private val logAdapter: LogAdapter,
    @param:Inject(DbConstant.DB_DEFAULT) private val sqlUtils: SqlUtils,
    @param:Inject(DbConstant.DB_DEFAULT) private val dataSource: DataSource,
    private val applicationService: ApplicationService,
    private val userService: UserService,
    private val roleService: RoleService,
    private val initDataService: InitDataService,
    private val runtimeConfigService: RuntimeConfigService,
    private val acpOauthServerAutoConfiguration: AcpOauthServerAutoConfiguration
) : AcpInitialization {
    override val name: String
        get() = "Data Initialization"

    private fun initTable() {
        ResourceUtil.getResourceAsString(
            "${DbConstant.SCHEMA_PATH}/${
                DbTypeUtil.getDbType(dataSource).name.lowercase()
            }/${DbConstant.SCHEMA_FILE}"
        )?.apply {
            for (sql in this.split(";")) {
                if (sql.trim { it <= ' ' }.length > 10) {
                    sqlUtils.sql(sql).update()
                }
            }
        }
    }

    private fun initData() {
        applicationService.getAppList().apply {
            if (this.isEmpty()) {
                logAdapter.info(">>>>>>>>>>>>>>>>>>>> begin init system resource data...")
                initDataService.doInitResources()
                logAdapter.info(">>>>>>>>>>>>>>>>>>>> init system resource data has finished!")
            }
            acpOauthServerAutoConfiguration.loadClientInfo()
        }
        userService.getUserVoListByRole(listOf(RoleCode.SUPER)).apply {
            if (this.isEmpty()) {
                logAdapter.info("admin user is not existed")
                logAdapter.info("begin init admin user...")
                roleService.getRoleList().filter { role -> role.code == RoleCode.SUPER }.let { roleList ->
                    initDataService.initAdminUser(roleList)
                }
                logAdapter.info("init admin user has finished!")
            }
        }
    }

    private fun loadSystemData() {
        logAdapter.info("begin load runtime config data...")
        runtimeConfigService.loadRuntimeConfig()
        logAdapter.info("load runtime config data has finished!")
    }

    override fun doInit() {
        val init = Solon.cfg().getBool(DbConstant.INIT_ENABLED_KEY, false)
        if (init) {
            initTable()
            initData()
        }
        loadSystemData()
    }
}